﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Sitecore.Data.Items;
using System.Data;
using Workflow.Alerts.DAL;
using Workflow.Alerts.Interfaces.ProfileSettings;
using workflow.Dal;
using System.Data.Objects;

namespace Workflow.Alerts
{
    public class MaterialsGridViewPresenter : Presenter
    {
        #region members
        private readonly IMaterialsGridView view;
        #endregion

        #region constructor
        public MaterialsGridViewPresenter(IMaterialsGridView _view)
            : this(_view, null)
        { }

        public MaterialsGridViewPresenter(IMaterialsGridView _view, ISessionProvider session)
            : base(_view, session)
        {
            view = base.GetView<IMaterialsGridView>();
            view.OnDelete += view_OnDelete;
            view.OnEditLoad += view_OnEditLoad;
            view.OnSave += view_OnSave;
            view.OnTableLoad += view_OnTableLoad;
            view.OnFirstLoad += view_LoadFromDbTemp;
            view.OnClearTempValues += view_OnClearTempValues;

        }

        #endregion

        #region private methods

        private void view_OnClearTempValues()
        {
            var tempAlertMaterials = TempAlertMaterials;
            var usedAlertMaterials = tempAlertMaterials.Where(am => am.Alert.id == view.AlertId).ToList();
            tempAlertMaterials = tempAlertMaterials.Except(usedAlertMaterials).ToList();

            TempAlertMaterials = tempAlertMaterials;
        }

        private void view_OnTableLoad()
        {
            using (WorkflowEntitySet context = new WorkflowEntitySet())
            {
                List<AlertMaterials> alertMaterials;

                if (view.StoreChangesInDb)
                {
                    var alert = context.Alert
                                        .Include("AlertMaterials")
                                        .Where(a => a.id == view.AlertId).First();

                    alertMaterials = alert.AlertMaterials.ToList<AlertMaterials>();
                }
                else
                {
                    alertMaterials = TempAlertMaterials;
                }

                List<MaterialGridClass> materialsList = new List<MaterialGridClass>();
                foreach (AlertMaterials alertMaterial in alertMaterials)
                {
                    if (alertMaterial.Materials == null)
                        alertMaterial.MaterialsReference.Load();
                    var m = new MaterialGridClass()
                 {
                     materialname = alertMaterial.Materials.name,
                     quantity = alertMaterial.quantity,
                     unit = WorkflowEnums.MaterialsUnits[alertMaterial.Materials.unit],
                     price = alertMaterial.price,
                     uitvoerder = alertMaterial.uitvoerd ?? false,
                     uitstel = alertMaterial.uitstel ?? false,
                     id = alertMaterial.id
                 };
                    materialsList.Add(m);
                }


                view.MaterialsTable = materialsList;
            }
        }

        private void view_OnSave(Int32? alertMaterialId)
        {
            List<AlertMaterials> listOfAlertMaterials = TempAlertMaterials;            
            using (WorkflowEntitySet context = new WorkflowEntitySet())
            {
                AlertMaterials alertMaterial;
                if (alertMaterialId.HasValue)
                {
                    if (view.StoreChangesInDb)
                        alertMaterial = context.AlertMaterials.Where(am => am.id == alertMaterialId.Value).First();
                    else
                    {
                        var oldRecord = listOfAlertMaterials.Where(am => am.id == alertMaterialId.Value).First();
                        alertMaterial = new AlertMaterials();
                        alertMaterial.id = oldRecord.id;
                        alertMaterial.Alert = context.Alert.Where(a => a.id == view.AlertId).First();
                        listOfAlertMaterials.Remove(oldRecord);
                    }
                }
                else
                {                    
                    alertMaterial = new AlertMaterials();
                    alertMaterial.Alert = context.Alert.Where(a => a.id == view.AlertId).First();
                    if (view.StoreChangesInDb)
                        context.AddToAlertMaterials(alertMaterial);
                }

                var material = context.Materials.Where(m => m.id == view.SelectedMaterial).First();

                alertMaterial.Materials = material;
                alertMaterial.quantity = view.SelectedQuantity;
                alertMaterial.uitstel = view.IsHerstel;
                alertMaterial.uitvoerd = view.IsUitvoerder;
                if (view.IsUitvoerder)
                    alertMaterial.price = view.SelectedQuantity * material.constructorPrice;
                else
                {
                    alertMaterial.price = view.SelectedQuantity * material.price;
                }

                if (view.StoreChangesInDb)
                    context.SaveChanges();
                else
                {

                    listOfAlertMaterials.Add(alertMaterial);
                    TempAlertMaterials = listOfAlertMaterials;
                }


                view_OnTableLoad();
            }
        }

        private void view_OnEditLoad(Int32? materialAlertId)
        {
            using (WorkflowEntitySet context = new WorkflowEntitySet())
            {
                var listOfAlertMaterials = TempAlertMaterials;
                var alert = context.Alert.Include("Municipality").Include("AlertMaterials").Where(a => a.id == view.AlertId).First();
                var materials = context.Materials.Where(m => m.Municipality.id == alert.Municipality.id).ToList();

                List<Materials> usedmaterials = new List<Materials>();
                if (view.StoreChangesInDb)
                {
                    foreach (var am in alert.AlertMaterials)
                    {
                        if (!am.MaterialsReference.IsLoaded)
                            am.MaterialsReference.Load();

                        usedmaterials.Add(am.Materials);
                    }
                }
                else
                {
                    foreach (var am in listOfAlertMaterials)
                    {
                        usedmaterials.Add(am.Materials);
                    }
                }
                foreach (var material in usedmaterials)
                {
                    var match = materials.Where(m => m.id == material.id).FirstOrDefault();
                    if (match != null)
                        materials.Remove(match);
                }
                //var materials1 = materials.Except(usedmaterials, ).ToList();

                var materials2 = materials.Select(x => new { x.id, name = string.Format("{0} ({1})", x.name, WorkflowEnums.MaterialsUnits[x.unit]) })
                                                 .ToDictionary(x => x.id, x => x.name);


                view.MaterialsList = materials2;
                view.SelectedQuantity = 1;
                view.IsUitvoerder = false;
                view.IsHerstel = false;

                if (materialAlertId.HasValue)
                {
                    AlertMaterials alertMaterial;
                    if (view.StoreChangesInDb)
                    {
                        alertMaterial = context.AlertMaterials.Where(am => am.id == materialAlertId.Value).First();
                        if (!alertMaterial.MaterialsReference.IsLoaded)
                            alertMaterial.MaterialsReference.Load();
                    }
                    else
                    {
                        alertMaterial = listOfAlertMaterials.Where(am => am.id == materialAlertId.Value).First();
                    }
                    view.SelectedQuantity = alertMaterial.quantity;
                    view.IsUitvoerder = alertMaterial.uitvoerd ?? false;
                    view.IsHerstel = alertMaterial.uitstel ?? false;

                    materials2.Add(alertMaterial.Materials.id, string.Format("{0} ({1})", alertMaterial.Materials.name, WorkflowEnums.MaterialsUnits[alertMaterial.Materials.unit]));
                    view.MaterialsList = materials2;
                    view.SelectedMaterial = alertMaterial.Materials.id;
                }
                else
                {
                    view.MaterialsList = materials2;
                }
            }
        }

        private void view_OnDelete(Int32 materialAlertId)
        {
            var listOfAlertMaterials = TempAlertMaterials;
            using (WorkflowEntitySet context = new WorkflowEntitySet())
            {
                if (view.StoreChangesInDb)
                {
                    context.DeleteObject(context.AlertMaterials.Where(am => am.id == materialAlertId).First());
                    context.SaveChanges();
                }
                else
                {
                    listOfAlertMaterials.Remove(TempAlertMaterials.Where(am => am.id == materialAlertId).First());
                    TempAlertMaterials = listOfAlertMaterials;
                }
                view_OnTableLoad();
            }
        }

        private void view_LoadFromDbTemp()
        {
            List<AlertMaterials> listOfalertMaterials = TempAlertMaterials;

            if (listOfalertMaterials.Where(am => am.Alert.id == view.AlertId).Any())
                return;

            using (WorkflowEntitySet context = new WorkflowEntitySet())
            {
                var alert = context.Alert
                                         .Include("AlertMaterials")
                                         .Where(a => a.id == view.AlertId).First();
                var alertMaterials = alert.AlertMaterials.ToList();
                foreach (var am in alertMaterials)
                {
                    am.MaterialsReference.Load();
                    listOfalertMaterials.Add(am);
                }

                TempAlertMaterials = listOfalertMaterials;
            }
        }

        #endregion

        private List<AlertMaterials> TempAlertMaterials
        {
            get
            {
                if (Session["TempAlertMaterials"] == null)
                    return new List<AlertMaterials>();
                return Session["TempAlertMaterials"] as List<AlertMaterials>;
            }
            set
            {
                Session["TempAlertMaterials"] = value;
            }
        }
    }
}
